﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using RobotOM;

namespace BarBarClosestNodesAddin
{
    public partial class MainForm : Form
    {
        public IRobotApplication RobotApp = null;
        private int num1 = 0;
        private int num2 = 0;

        private Vector3 PointLineClosestPoint(Vector3 point, Vector3 linePoint, Vector3 lineDirection)
        {
            Vector3 res;
            res = point - linePoint;
            double c1 = res.DotProduct(lineDirection);
            double c2 = lineDirection.DotProduct(lineDirection);
            double b = c1/c2;
            res = linePoint + lineDirection * b;
            return res;
        }

        private void SegmentSegmentClosestPoint(Vector3 S0Start, Vector3 S0Stop, 
            Vector3 S1Start, Vector3 S1Stop, out Vector3 Segment0Closest, out Vector3 Segment1Closest )
        {
            const double cSMALL_NUM = 0.000000001;
            Vector3 u = S0Stop - S0Start;
            Vector3 v = S1Stop - S1Start;
            Vector3 w = S0Start - S1Start;

            double a = u.DotProduct(u);
            double b = u.DotProduct(v);
            double c = v.DotProduct(v);
            double smallD = u.DotProduct(w);
            double e = v.DotProduct(w);
            double largeD = a * c - b * b;

            double sD = largeD;
            double tD = largeD;
            double sN;
            double tN;

            if (largeD < cSMALL_NUM)
            {
                sN = 0.0;
                sD = 1.0;
                tN = e;
                tD = c;
            }
            else
            {
                sN = (b * e - c * smallD);
                tN = (a * e - b * smallD);
                if (sN < 0.0)
                {
                    sN = 0.0;
                    tN = e;
                    tD = c;
                }
                else if (sN > sD)
                {
                    sN = sD;
                    tN = e + b;
                    tD = c;
                }
            }

            if (tN < 0.0) 
            {
                tN = 0.0;
                // recompute sc for this edge
                if (-smallD < 0.0) 
                    sN = 0.0;
                else if (-smallD > a) 
                    sN = sD;
                else
                {
                    sN = -smallD;
                    sD = a;
                }
            }
            else if (tN > tD)
            {
                tN = tD;
                // recompute sc for this edge
                if ((-smallD + b) < 0.0)
                    sN = 0;
                else if ((-smallD + b) > a)
                    sN = sD;
                else
                {
                    sN = (-smallD + b);
                    sD = a;
                }
            }

            double sc, tc;

            if (Math.Abs(sN) < cSMALL_NUM) 
            sc = 0.0;
            else
            sc = sN/sD;

            if (Math.Abs(tN) < cSMALL_NUM) 
            tc = 0.0;
            else
            tc = tN/tD;

            Segment0Closest = S0Start + u * sc;
            Segment1Closest = S1Start + v * tc;
        }

        public MainForm()
        {
            InitializeComponent();
            RobotApp = new RobotApplication();
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            System.Windows.Forms.TextBox box = sender as System.Windows.Forms.TextBox;
            int i = 0;
            try
            {
                i =  Convert.ToInt32(box.Text);
                if (i > 0)
                    box.BackColor = Color.Lime;
                else
                    box.BackColor = Color.Red;
            }
            catch
            {
                box.BackColor = Color.Red;
            }
            if (textBox1 == box)
                num1 = i;
            else
                num2 = i;
        }

        private IRobotBar get_Bar(int num, IRobotCollection set)
        {
            IRobotBar bar;
            for (int i = 1; i < set.Count+1; i++)
            {
                bar = set.Get(i) as IRobotBar;
                if (bar.Number == num)
                    return bar;
            }
            throw new Exception();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (RobotApp == null)
            {
                System.Windows.Forms.MessageBox.Show("Robot not active or missing");
                return;
            }

            if (RobotApp.Project.IsActive == 0)
            {
                System.Windows.Forms.MessageBox.Show("No any project opened in Robot");
                return;
            }

            if (num1 > 0 && num2 > 0 && num1 == num2)
            {
                System.Windows.Forms.MessageBox.Show("Same bars, please select different");
                return;
            }

            if (num1 > 0 && num2 > 0)
            {
                IRobotCollection bars = RobotApp.Project.Structure.Bars.GetAll();
                IRobotBar bar1;
                IRobotBar bar2;
                try
                {
                    bar1 = get_Bar(num1, bars);
                    bar2 = get_Bar(num2, bars);
                }
                catch
                {
                    System.Windows.Forms.MessageBox.Show("Selected bars does not exist");
                    return;
                }

                IRobotNode start_node_1 = RobotApp.Project.Structure.Nodes.Get(bar1.StartNode) as IRobotNode;
                IRobotNode end_node_1 = RobotApp.Project.Structure.Nodes.Get(bar1.EndNode) as IRobotNode;
                IRobotNode start_node_2 = RobotApp.Project.Structure.Nodes.Get(bar2.StartNode) as IRobotNode;
                IRobotNode end_node_2 = RobotApp.Project.Structure.Nodes.Get(bar2.EndNode) as IRobotNode;

                Vector3 start1 = new Vector3(start_node_1.X, start_node_1.Y, start_node_1.Z); 
                Vector3 end1 = new Vector3(end_node_1.X, end_node_1.Y, end_node_1.Z);
                Vector3 start2 = new Vector3(start_node_2.X, start_node_2.Y, start_node_2.Z);
                Vector3 end2 = new Vector3(end_node_2.X, end_node_2.Y, end_node_2.Z);
                Vector3 nearPoint1; 
                Vector3 nearPoint2;
                SegmentSegmentClosestPoint(start1, end1, start2, end2, out nearPoint1, out nearPoint2);
                Double dis = nearPoint1.Distance(nearPoint2);
                if (dis < 0.00001)
                {
                    System.Windows.Forms.MessageBox.Show("Bars is crossing, command canceled");
                    return;
                }

                if (nearPoint1 != start1 && nearPoint1 != end1 && nearPoint1 != start2 && nearPoint1 != end2)
                    RobotApp.Project.Structure.Nodes.Create(
                        RobotApp.Project.Structure.Nodes.FreeNumber, nearPoint1.X, nearPoint1.Y, nearPoint1.Z);

                if (nearPoint2 != start1 && nearPoint2 != end1 && nearPoint2 != start2 && nearPoint2 != end2)
                    RobotApp.Project.Structure.Nodes.Create(
                        RobotApp.Project.Structure.Nodes.FreeNumber, nearPoint2.X, nearPoint2.Y, nearPoint2.Z);
            }
        }
    }
}
